class WordController < ApplicationController
  before_filter :login_required
  layout "main"
  
  def index
    list
    render :action=> "list"
  end
  
  def list
    @current = "word"
    @page_title = "All Words"
    
    user = User.find_by_id(session[:user].id)
    words = user.words
    words = filter_excluded_words(user, words)
    
    @word_pages, @words = paginate_collection words, 
                          :page => params[:page], :per_page => 100

  end
  
  def edit_word
  
    @current = "word"
    @page_title = "Edit word"
    user = User.find_by_id(session[:user].id)
    
    story = user.stories.find_by_id(params[:story_id], :select => "id")
    @word = story.words.find_by_id(params[:id])

    if request.post?

     message = ""
     
     if new_word = Word.find_by_word(params[:word][:word])
      
      # if the word already exists in words...
      unless user.words.find_by_id(new_word.id)
      
        # ... and the word doesn't yet belong to the user 
        user.words << new_word
        logger.info("Edit Word: Added user <-> word relationship (1)")
      end
      
      unless story.words.find_by_id(new_word.id)
        
        # ... andthe doesn't yet belong to the story  
        story.words << new_word
        message << "#{new_word.word} has been saved."
        logger.info("Edit Word: Added story <-> word relationship (2)")
        
      end
      
     else
     
      # if the word doesn't exists, create a new word and associate it
      # with the user and story...
      new_word = Word.create(:word => params[:word][:word])
      user.words << new_word
      story.words << new_word
      
      # ...and delete the old word <-> story relationship
      # for the old word
      @word.stories.delete(story)
      
      logger.info("Edit Word: Created new word and added user <-> word relationship and story <-> word relationship. Then deleted old story <-> relationship (3)")

     end
     
      # destroy the old word if it isn't 
      # being used by anyone else
      if new_word.id != @word.id
        
        message << "#{@word.word} has been changed to #{new_word.word}."
        
        @word.stories.delete(story)
        @word.users.delete(user)
        logger.info("Edit Word: Removed user <-> word relationship and story <-> word relationship (4)")  
        
      else
        message << "#{@word.word} was not modified."
      end
      
      unless Word.find(params[:id]).stories.count > 0
      
        Word.find(params[:id]).destroy
        logger.info("Edit Word: This word is no longer being used, so I destroyed it. (5)")
        
      end
      
      flash[:notice] = message
      redirect_to :action => 'story_words', :story_id => @word[:story_id]
      
    end
      
  end
  
  def view
  
    if params[:relationship_id]
      @current = "shared_words"
      @owner = User.find(:first,
                         :select => "users.first_name, users.last_name, users.login, users.id",
                         :joins => "JOIN relationships ON (users.id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (users.id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id})",
                         :conditions => ["relationships.validated AND users.id <> #{session[:user].id} AND relationships.id = ?", params[:relationship_id]]) 
      @page_title = "All Words Shared by #{@owner.first_name} #{@owner.last_name} (#{@owner.login})"
    else
      @current = "word"
    end

    user = User.find_by_id(session[:user].id)
    
    if params[:story_id] then 
      
      if params[:relationship_id]
        @story = Story.find(params[:story_id],
                          :select => "stories.id, stories.title, stories.created_at, stories.updated_at",
                          :joins => "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                        "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} ",
                          :conditions => ["stories.id = ?",params[:story_id]])
      else
        @story = user.stories.find_by_id(params[:story_id], :select => "id, title, created_at, updated_at")
      end
      
      @word = @story.words.find_by_id(params[:id])
      
    else
      
      @word = user.words.find_by_id(params[:id])
      
    end
    
    @story_count = @word.stories.count
    
    @page_title = @word[:word]
    
  end
 
  def from_story
    @current = "word"

    user = User.find_by_id(session[:user].id)
    @story = user.stories.find_by_id(params[:id])
    
    @page_title = "Words from #{@story.title}"
    
    # Get all the words for the story                   
    words = @story.words
    
    words = filter_excluded_words(user, words)
    
    @word_pages, @words = paginate_collection words, 
                          :page => params[:page], :per_page => 100
  end
  
  def from_other_users_stories
    @current = "from_other_users_stories"
    
    if params[:id]
      @story = Story.find(params[:id],
                          :select => "stories.id, stories.title, stories.created_at, stories.updated_at",
                          :joins => "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                        "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} ",
                          :conditions => ["stories.id = ?",params[:story_id]])
    end
    
    if params[:relationship_id]
      @owner = User.find(:first,
                         :select => "users.first_name, users.last_name, users.login, users.id",
                         :joins => "JOIN relationships ON (users.id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (users.id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id})",
                         :conditions => ["relationships.validated AND users.id <> #{session[:user].id} AND relationships.id = ?", params[:relationship_id]]) 
      
      @word_pages, @words = paginate_collection Word.find(:all,
                                                              :select => "DISTINCT words.word",
                                                              :joins => "JOIN stories ON stories.id = words.story_id " +
                                                                        "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                        "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} " +
                                                                        "LEFT JOIN duds ON duds.word = words.word AND duds.user_id = #{session[:user].id}",
                                                              :conditions => ["relationships.validated AND relationships.id = ? AND duds.word IS NULL",params[:relationship_id]],
                                                                            :order => "words.word"), 
                                                                            :page => params[:page], :per_page => 100
    else
      
      @word_pages, @words = paginate_collection Word.find(:all,
                                                          :select => "DISTINCT words.word",
                                                          :joins => "JOIN stories ON stories.id = words.story_id " +
                                                                    "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                    "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} " +
                                                                    "LEFT JOIN duds ON duds.word = words.word AND duds.user_id = #{session[:user].id}",
                                                          :conditions => "relationships.validated AND duds.word IS NULL",
                                                                        :order => "words.word"), 
                                                                        :page => params[:page], :per_page => 100
    end
    
    if params[:id]
      @page_title = "Words from '#{@story.title}' Shared by #{@owner.first_name} #{@owner.last_name} (#{@owner.login})"
    elsif params[:relationship_id]
      @page_title = "All Words Shared by #{@owner.first_name} #{@owner.last_name} (#{@owner.login})"
    else
      @page_title = "All Shared Words"
    end

  end
      
  def in_category
    user = User.find_by_id(session[:user].id)
    category_title = params[:id]
    @category = user.categories.find_by_title(category_title)
    @page_title = "Words in the \"<i>#{@category.title}</i>\" Category"
    
    stories = @category.stories
    
    words = []
    stories.each do |story|
      words.concat(story.words)
    end
    
    @word_pages, @words = paginate_collection filter_excluded_words(user, words.uniq), :page => params[:page], :per_page => 100
  end
  
  def study
    @current = "word"
    @page_title = "Study all words"
    user = User.find_by_id(session[:user].id)
    
    @word_pages, @words = paginate_collection filter_excluded_words(user, user.words), :page => params[:page], :per_page => 1
    
  end
  
  def study_story_words
    @current = "story"
    user = User.find_by_id(session[:user].id)
    @story = user.stories.find(params[:id])
    @page_title = "Study Words from \"#{@story.title}\""
    
    @word_pages, @words = paginate_collection filter_excluded_words(user, @story.words), :page => params[:page], :per_page => 1
    
  end
  
  def study_shared_words
    @current = "shared_words"
    
    if params[:story_id]
      @story = Story.find(params[:story_id],
                          :select => "stories.id, stories.title, stories.created_at, stories.updated_at",
                          :joins => "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                        "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} ",
                          :conditions => ["stories.id = ?",params[:story_id]])
    end
    
    if params[:relationship_id]
      @owner = User.find(:first,
                         :select => "users.first_name, users.last_name, users.login, users.id",
                         :joins => "JOIN relationships ON (users.id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (users.id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id})",
                         :conditions => ["relationships.validated AND users.id <> #{session[:user].id} AND relationships.id = ?", params[:relationship_id]]) 
      
      @word_pages, @words = paginate_collection Word.find(:all,
                                                              :select => "DISTINCT words.word",
                                                              :joins => "JOIN stories ON stories.id = words.story_id " +
                                                                        "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                        "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} " +
                                                                        "LEFT JOIN duds ON duds.word = words.word AND duds.user_id = #{session[:user].id}",
                                                              :conditions => ["relationships.validated AND relationships.id = ? AND duds.word IS NULL",params[:relationship_id]],
                                                                            :order => "words.word"), 
                                                                            :page => params[:page], :per_page => 1
    else
      
      @word_pages, @words = paginate_collection Word.find(:all,
                                                          :select => "DISTINCT words.word",
                                                          :joins => "JOIN stories ON stories.id = words.story_id " +
                                                                    "JOIN relationships ON (stories.user_id = relationships.user_id_b AND relationships.user_id_a = #{session[:user].id}) OR (stories.user_id = relationships.user_id_a AND relationships.user_id_b = #{session[:user].id}) " +
                                                                    "JOIN shared_stories ON stories.id = shared_stories.story_id AND shared_stories.borrower_id = #{session[:user].id} " +
                                                                    "LEFT JOIN duds ON duds.word = words.word AND duds.user_id = #{session[:user].id}",
                                                          :conditions => "relationships.validated AND duds.word IS NULL",
                                                                        :order => "words.word"), 
                                                                        :page => params[:page], :per_page => 1
    end
    
    if params[:story_id]
      @page_title = "Words from '#{@story.title}' Shared by #{@owner.first_name} #{@owner.last_name} (#{@owner.login})"
    elsif params[:relationship_id]
      @page_title = "All Words Shared by #{@owner.first_name} #{@owner.last_name} (#{@owner.login})"
    else
      @page_title = "All Shared Words"
    end
    
  end
  
  def study_group_words
    @current = "word"
    @group = Group.find(params[:group_id])
    @page_title = "Study Words from the \"<i>#{@group.title}</i>\" Group"
    
    @word_pages, @words = paginate_collection Word.find(:all,
                                                        :joins => "as w inner join groupings as g on g.story_id = w.story_id LEFT JOIN duds ON duds.word = w.word AND duds.user_id = #{session[:user].id}", 
                                                        :conditions => ["g.group_id = ? AND duds.word IS NULL",params[:group_id]], 
                                                        :order => "word",
                                                        :select => "DISTINCT w.word"), 
                                                        :page => params[:page], :per_page => 1
    
  end
  
  def excluded
    @current = "excluded"
    @page_title = "Excluded Words"
    user = User.find_by_id(session[:user].id)
    @excluded_words = user.word_exclusions
    @excluded_word_pages, @excluded_words = paginate_collection @excluded_words, :page => params[:page], :per_page => 100
  end
  
  def exclude
  
    # Add the word to the excluded_words
    user = User.find_by_id(session[:user].id)
    if word = user.words.find_by_id(params[:id])
      excluded_word = ExcludedWord.new(:user_id => user.id, :word_id => word.id)
      if excluded_word.save
       flash[:notice] = "Now excluding \"#{word.word}\""
      end
    end
    
    redirect_to @request.env["HTTP_REFERER"]
    
  end
  
  def stop_excluding
  
    # Remove the word / user relationship from excluded_words
    user = User.find_by_id(session[:user].id)
    excluded_word = user.word_exclusions.find(params[:id])
    ExcludedWord.delete_all(["user_id = ? and word_id = ?", user.id, excluded_word.id])
    
    flash[:notice] = "\"#{excluded_word.word}\" has been removed from your Excluded Words list."
    redirect_to :controller => "word", :action => "excluded"
    
  end
  
  private
  
  def filter_excluded_words(user, words) 

    # Remove any excluded words from the 
    # passed set of words then return filtered
    # set back to the calling class.

    @words = []
    
    # Find all the excluded words
    excluded_words = user.word_exclusions
    
    # Filter out any excluded words
    words.each do |word|
       if !excluded_words.find_by_id(word.id)
        @words << word
       end
    end 
    
    return @words
    
  end
end
